package com.hang.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hang.entity.Comment;
import com.hang.entity.TbDocument;
import com.hang.exception.MyException;
import com.hang.exception.MyExceptionEnum;
import com.hang.mapper.CommentMapper;
import com.hang.mapstruct.CommentMapStruct;
import com.hang.mapstruct.DocumentMapStruct;
import com.hang.model.dto.base.ConditionDTO;
import com.hang.model.dto.request.DocumentDeleteDTO;
import com.hang.model.dto.request.DocumentModelDTO;
import com.hang.model.dto.request.ModuleConditionDTO;
import com.hang.model.dto.response.DocumentQueryListVO;
import com.hang.model.vo.CommentInfoVO;
import com.hang.model.vo.DocumentDetailVO;
import com.hang.model.vo.DocumentInfoVO;
import com.hang.mongoEntity.CommentEntity;
import com.hang.mongoEntity.DocumentEntity;
import com.hang.repository.DocumentEntityRepository;
import com.hang.service.ICommentService;
import com.hang.service.ITbDocumentService;
import com.hang.mapper.TbDocumentMapper;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

/**
 *
 */
@Service
@AllArgsConstructor
public class TbDocumentServiceImpl extends ServiceImpl<TbDocumentMapper, TbDocument>
    implements ITbDocumentService {

    private DocumentMapStruct documentMapStruct;

    private MongoTemplate mongoTemplate;

    private ICommentService commentService;
    /**
     * 创建文档
     * @param documentModelDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createDocument(DocumentModelDTO documentModelDTO) {
        TbDocument document = documentMapStruct.documentModelDTOToTbDocument(documentModelDTO);

        //先将富文本内容存储进MongoDB
        String content = Optional.ofNullable(documentModelDTO.getContent()).orElse("");
        if(StrUtil.isNotBlank(content)){
            String mongoId = IdWorker.getIdStr();

            mongoTemplate.save(new DocumentEntity(mongoId,content));
            document.setMongoId(mongoId);
        }

        //将内容持久同步到Mysql中
        this.save(document);
   }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDocument(DocumentModelDTO documentModelDTO) {
        Long documentId = documentModelDTO.getDocumentId();

        if(ObjectUtil.isEmpty(documentId)){
            throw new MyException(MyExceptionEnum.ID_IS_NULL);
        }

        TbDocument dbDocument = Optional.ofNullable(this.getById(documentId)).orElse(null);

        if(ObjectUtil.isNull(dbDocument)){
            throw new MyException(MyExceptionEnum.DATA_DOES_NOT_EXIST);
        }

        //需要判断是否是本人创建的文档
        Long userId = documentModelDTO.getUserId();
        if(userId.compareTo(dbDocument.getUserId())!=0){
            throw new MyException(MyExceptionEnum.OPERATOR_UPDATE_EXCEPTION);
        }

        String mongoId = Optional.ofNullable(dbDocument.getMongoId()).orElse("");

        //否则修改相对应的数据内容
        BeanUtils.copyProperties(documentModelDTO,dbDocument);

        //修改相关的文档内容
        if(StrUtil.isNotBlank(documentModelDTO.getContent())){
            if(StrUtil.isNotBlank(mongoId)){
                //搜索查询出内容，然后更新
                DocumentEntity documentEntity = Optional.ofNullable(mongoTemplate.findById(mongoId,DocumentEntity.class)).orElse(new DocumentEntity(IdWorker.getIdStr()));
                documentEntity.setContent(documentModelDTO.getContent());

                Query query = new Query(Criteria.where("_id").is(mongoId));
                Update update = new Update();
                update.set("content",documentEntity.getContent());
                mongoTemplate.upsert(query,update,DocumentEntity.class);

                dbDocument.setMongoId(documentEntity.getMongoId());
            }else {
                //插入一条数据
                String mongodbId = IdWorker.getIdStr();
                mongoTemplate.save(new DocumentEntity(mongodbId,documentModelDTO.getContent()));
                dbDocument.setMongoId(mongodbId);
            }
        }

        //持久化到数据库层
        this.updateById(dbDocument);
    }

    /**
     * 批量删除文档
     * @param documentDeleteDTOList
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteDocumentList(List<DocumentDeleteDTO> documentDeleteDTOList) {
        if(ObjectUtil.isNull(documentDeleteDTOList) || documentDeleteDTOList.size() < 1){
            throw new MyException(MyExceptionEnum.ID_IS_NULL);
        }

        //批量检查删除
        documentDeleteDTOList.forEach(
                this::deleteDocument
        );
    }

    /**
     * 根据条件分页搜索文档
     * 模糊搜索：文档标题,创建人搜索符合条件
     *
     * @param conditionDTO
     * @return
     */
    @Override
    public DocumentQueryListVO getListByCondition(ModuleConditionDTO conditionDTO) {
        if(ObjectUtil.isEmpty(conditionDTO)){
            throw new MyException(MyExceptionEnum.OBJECT_IS_NULL);
        }

        //搜索条件
        Long moduleId = conditionDTO.getModuleId();

        String condition = Optional.ofNullable(conditionDTO.getCondition()).orElse("");
        Integer pageNum = conditionDTO.getPageNum();
        Integer pageSize = conditionDTO.getPageSize();

        QueryWrapper<TbDocument> documentQueryWrapper = new QueryWrapper<>();
        documentQueryWrapper.lambda().eq(TbDocument::getModuleId,moduleId);

        if(StrUtil.isNotBlank(condition)){
            documentQueryWrapper.and(
                    wrapper -> wrapper
                            .lambda()
                            .like(TbDocument::getDocumentTitle,condition)
                            .or()
                            .like(TbDocument::getRealName,condition)
            );
        }

        documentQueryWrapper.lambda().orderByDesc(TbDocument::getCreateTime);

        Page<TbDocument> page = new Page<>(pageNum,pageSize);
        List<TbDocument> documentList = Optional.ofNullable(this.baseMapper.selectPage(page,documentQueryWrapper).getRecords()).orElse(new LinkedList<>());

        DocumentQueryListVO documentQueryListVO = new DocumentQueryListVO();
        documentQueryListVO.setTotal(Optional.ofNullable(this.baseMapper.selectCount(documentQueryWrapper)).orElse(0));
        documentQueryListVO.setDocumentInfoVOList(documentMapStruct.documentListToDocumentInfoVOList(documentList));

        return documentQueryListVO;
    }

    /**
     * 根据id获取文档详情
     *      基本内容展示
     *      富文本内容展示
     *      评论列表展示
     * @param documentId
     * @return
     */
    @Override
    public DocumentDetailVO getDocumentDetailById(Long documentId) {
        if(ObjectUtil.isNull(documentId)){
            throw new MyException(MyExceptionEnum.ID_IS_NULL);
        }

        TbDocument dbDocument = Optional.ofNullable(this.getById(documentId)).orElse(null);

        if(ObjectUtil.isEmpty(dbDocument)){
            throw new MyException(MyExceptionEnum.DATA_DOES_NOT_EXIST);
        }

        DocumentDetailVO documentDetailVO = documentMapStruct.documentToDocumentDetailVO(dbDocument);

        //内容填充[富文本]
        String mongoId = dbDocument.getMongoId();

        if(StrUtil.isNotBlank(mongoId)){
            Query query = new Query(Criteria.where("_id").is(mongoId));
            DocumentEntity documentEntity = Optional.ofNullable(mongoTemplate.findOne(query, DocumentEntity.class)).orElse(new DocumentEntity());
            if(documentEntity.getContent()!=null){
                documentDetailVO.setContent(documentEntity.getContent());
            }
        }

        //评论列表展开
        QueryWrapper<Comment> commentQueryWrapper = new QueryWrapper<>();
        commentQueryWrapper.lambda().in(Comment::getDocumentId,documentId);

        //评论的基础属性复制
        List<CommentInfoVO> commentInfoVOList = commentService.getCommonListInfo(documentId,1);

        documentDetailVO.setCommentInfoVOList(commentInfoVOList);

        return documentDetailVO;
    }

    //删除文档
    private void deleteDocument(DocumentDeleteDTO documentDeleteDTO){
        if(ObjectUtil.isEmpty(documentDeleteDTO)){
            throw new MyException(MyExceptionEnum.OBJECT_IS_NULL);
        }

        Long userId = documentDeleteDTO.getUserId();
        Long documentId = documentDeleteDTO.getDocumentId();

        Long dbUserId = Optional.ofNullable(this.getById(documentId).getUserId()).orElse(null);

        if(dbUserId == null){
            throw new MyException(MyExceptionEnum.DATA_DOES_NOT_EXIST);
        }

        if(dbUserId.compareTo(userId)!=0){
            throw new MyException(MyExceptionEnum.OPERATOR_DELETE_EXCEPTION);
        }

        //否则删除相关文档
        this.removeById(documentId);
    }
}